// $Id: jabber.cpp 12 2009-05-04 19:51:42Z longerdev $

/*
Copyright (C) 2008 Longer <longerdev@gmail.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <sys/utsname.h>
#include <syslog.h>
#include "jabber.h"

JabCon::JabCon(){
	isExit = 0;
	serv = "";
	port = 0;
	login = "";
	pass = "";
	myjid = "";
	destjid = "";
}

void JabCon::JConnect(){
	JID jid(login);
	j = new Client(jid, pass);
	if (serv != "")
		j->setServer(serv);
	if (port != 0)
		j->setPort(port);
	j->registerMessageHandler(this);
	j->registerConnectionListener(this);
	j->setPresence(PresenceAvailable, 5);

	utsname u;
	uname(&u);
	j->disco()->setVersion("JIDs tunnel", VERSION, u.sysname);

	j->connect();

	return;
}

void JabCon::handleMessage(Stanza *stanza, MessageSession*){
	std::string msg = stanza->body();
	if (msg != ""){
		std::string msg_to = "";
		std::string tfrom = stanza->from().full();
		tfrom = tfrom.substr(0, tfrom.find("/"));
		
		//cerr << destjid;

		if (tfrom == myjid)
			msg_to = destjid;
		else if (tfrom == destjid)
			msg_to = myjid;

		if (msg_to != ""){
			Stanza *s = Stanza::createMessageStanza(msg_to, msg);
			j->send(s);
		}
	}

	return;
}

void JabCon::onConnect(){
	return;
}

bool JabCon::onTLSConnect(const CertInfo &cinfo){
	return true;
}

void JabCon::onDisconnect(ConnectionError e){
	switch (e) {
		case ConnAuthenticationFailed:{
			syslog(LOG_ERR, "Authentication failed. Username/password wrong or account does not exist.");
			isExit = 1;
			break;
		}

		case ConnUserDisconnected:
			syslog(LOG_ERR, "The user (or higher-level protocol) requested a disconnect.");
			break;

		case ConnNotConnected:
			syslog(LOG_ERR, "There is no active connection.");
			break;

		case ConnCompressionFailed:
			syslog(LOG_ERR, "Negotiating/initializing compression failed.");
			break;

		case ConnTlsNotAvailable:
			syslog(LOG_ERR, "ConnTlsNotAvailable.");
			break;

		case ConnTlsFailed:
			syslog(LOG_ERR, "The server's certificate could not be verified or the TLS handshake did not complete successfully.");
			break;

		case ConnNoSupportedAuth:
			syslog(LOG_ERR, "The auth mechanisms the server offers are not supported or the server offered no auth mechanisms at all.");
			break;

		case ConnOutOfMemory:
			syslog(LOG_ERR, "Out of memory.");
			break;

		case ConnDnsError:
			syslog(LOG_ERR, "Resolving the server's hostname failed.");
			break;

		case ConnConnectionRefused:
			syslog(LOG_ERR, "The connection was refused by the server (on the socket level).");
			break;

		case ConnParseError:
			syslog(LOG_ERR, "An XML parse error occurred.");
			break;

		case ConnIoError:
			syslog(LOG_ERR, "An I/O error occured.");
			break;

		case ConnProxyNoSupportedAuth:
			syslog(LOG_ERR, "The HTTP/SOCKS5 proxy requires an unsupported auth mechanism.");
			break;

		case ConnProxyAuthFailed:
			syslog(LOG_ERR, "HTTP/SOCKS5 proxy authentication failed.");
			break;

		case ConnProxyAuthRequired:
			syslog(LOG_ERR, "The HTTP/SOCKS5 proxy requires authentication.");
			break;

		case ConnStreamClosed:
			syslog(LOG_ERR, "The stream has been closed (by the server).");
			break;

		case ConnStreamVersionError:
			syslog(LOG_ERR, "The incoming stream's version is not supported");
			break;

		case ConnStreamError:
			syslog(LOG_ERR, "A stream error occurred. The stream has been closed.");
			break;

		case ConnNoError:
			// Disconnected from server without errors
			isExit = 1;
			break;
	}

	syslog(LOG_ERR, "Disconnect error id: %d", e);

	return;
}

void JabCon::setServer(const std::string server){
	serv = server;
}

void JabCon::setPort(const int sPort){
	port = sPort;
}

void JabCon::setAuthData(const std::string sLogin, const std::string sPass){
	login = sLogin;
	pass = sPass;
}

void JabCon::setJIDs(const std::string sMyJID, const std::string sDestJID){
	myjid = sMyJID;
	destjid = sDestJID;
}

